import logging

import requests

from django.conf import settings

from mobsf.MobSF.utils import (
    file_size,
    get_config_loc,
    upstream_proxy,
)

logger = logging.getLogger(__name__)


class VirusTotal:
    base_url = settings.VIRUS_TOTAL_BASE_URL

    def get_report(self, file_hash):
        """
        Get Report from VT.

        :param file_hash: md5/sha1/sha256
        :return: json response / None
        """
        try:
            url = self.base_url + 'report'
            params = {
                'apikey': settings.VT_API_KEY,
                'resource': file_hash}
            headers = {'Accept-Encoding': 'gzip, deflate'}
            try:
                proxies, verify = upstream_proxy('https')
            except Exception:
                logger.exception('Setting upstream proxy')
            try:
                response = requests.get(
                    url,
                    params=params,
                    headers=headers,
                    proxies=proxies,
                    verify=verify)
                if response.status_code == 403:
                    logger.error(
                        'VirusTotal Permission denied, wrong api key?')
                    return None
            except Exception:
                logger.error(
                    'VirusTotal ConnectionError, check internet connectivity')
                return None
            try:
                json_response = response.json()
                return json_response
            except ValueError:
                return None
        except Exception:
            logger.exception('VirusTotal get_report')
            return None

    def upload_file(self, file_path):
        """
        Upload File to VT.

        :param file_path: file path to upload
        :return: json response / None
        """
        try:
            url = self.base_url + 'scan'
            if file_size(file_path) > 31:
                logger.warning('VirusTotal Public API does '
                               'not support files above 32 MB')
                return None
            files = {'file': open(file_path, 'rb')}
            headers = {'apikey': settings.VT_API_KEY}
            try:
                proxies, verify = upstream_proxy('https')
            except Exception:
                logger.exception('Setting upstream proxy')
            try:
                response = requests.post(
                    url,
                    files=files,
                    data=headers,
                    proxies=proxies,
                    verify=verify)
                if response.status_code == 403:
                    logger.error(
                        'VirusTotal Permission denied, wrong api key?')
                    return None
            except Exception:
                logger.error(
                    'VirusTotal Connection Error, check internet connectivity')
                return None
            json_response = response.json()
            return json_response

        except Exception:
            logger.exception('VirusTotal upload_file')
            return None

    def get_result(self, file_path, file_hash):
        """
        Get Results from VT.

        Uploading a file and getting the approval msg from VT
        or fetching existing report
        :param file_path: file's path
        :param file_hash: file's hash - md5/sha1/sha256
        :return: VirusTotal result json / None upon error
        """
        try:
            logger.info('VirusTotal: Check for existing report')
            report = self.get_report(file_hash)
            # Check for existing report
            if report:
                if report['response_code'] == 1:
                    logger.info('VirusTotal: %s', report['verbose_msg'])
                    return report
            if settings.VT_UPLOAD:
                logger.info('VirusTotal: file upload')
                upload_response = self.upload_file(file_path)
                if upload_response:
                    logger.info('VirusTotal: %s',
                                upload_response['verbose_msg'])
                return upload_response
            else:
                logger.info('VirusTotal Scan not performed as file'
                            ' upload is disabled in %s. '
                            'To enable file upload, '
                            'set VT_UPLOAD to True.', get_config_loc())
                message = ('Scan not performed, VirusTotal file'
                           f' upload disabled in {get_config_loc()}')
                report = {
                    'verbose_msg': message,
                    'positives': 0,
                    'total': 0}
                return report
        except Exception:
            logger.exception('VirusTotal get_result')
